/*
 * Copyright 2009 BioTeam Inc
 * 
 * Licensed under License GNU LESSER GENERAL PUBLIC LICENSE version 3.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.gnu.org/copyleft/lesser.html
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package net.bioteam.appweb.gwt.apps.client.dataanalysis;

import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;

import net.bioteam.appweb.datatype.RestrictedSelection;
import net.bioteam.appweb.gwt.apps.client.program.MyDataItem;
import net.bioteam.appweb.gwt.apps.client.program.ProgramForm;
import net.bioteam.appweb.gwt.apps.clientandserver.Constant;
import net.bioteam.appweb.gwt.apps.clientandserver.dataanalysis.FormData;
import net.bioteam.appweb.model.Paragraph;
import net.bioteam.appweb.model.Parameter;
import net.bioteam.appweb.model.Program;
import net.bioteam.appweb.submit.ProgramValueBean;

import com.google.gwt.user.client.Window;
import com.smartgwt.client.widgets.form.fields.FormItem;
import com.smartgwt.client.widgets.form.fields.HiddenItem;
import com.smartgwt.client.widgets.form.fields.SectionItem;
import com.smartgwt.client.widgets.form.fields.SelectItem;

public class DataProgramForm extends ProgramForm
{

	public DataProgramForm()
	{
		super();
		setAction("apps/user/dataprogramhandler");
	}

	FormData data;
	ProgramValueBean bean;

	public FormData getFormData()
	{
		return data;
	}

	public void setFormData(FormData d)
	{
		data = d;

		bean = d.bean;
		Program program = bean.getProgram();
		Window.setTitle(program.getName());

		FormItem fi = null;
		List<FormItem> items = new LinkedList<FormItem>();
		fi = new HiddenItem("_program");
		fi.setValue(program.getName());
		items.add(fi);

		fi = new HiddenItem(Constant.program_form_action_name);
		fi.setValue(Constant.run_action);
		items.add(fi);

		fi = new HiddenItem(Constant.progranm_form_cluster_name);
		fi.setValue("-1");
		items.add(fi);

		fi = new HiddenItem("_serviceid");
		fi.setValue(data.map.getFilekey());
		items.add(fi);

		// this.

		for (Parameter param : program.getParameters())
		{
			if (data.ommitted.contains(param.getName()))
			{
				continue;
			}
			if (data.hidden.contains(param.getName()))
			{
				fi = new HiddenItem(param.getName());
				fi.setValue(data.bean.getValue(param.getName()));
				items.add(fi);
				continue;
			}

			if (param.isHidden())
			{
				String value = bean.getValue(param.getName());
				fi = new HiddenItem(param.getName());
				fi.setValue(value);
				items.add(fi);
			} else
			{
				switch (param.getType())
				{
				case BooleanType:
					items.add(addBooleanField(param, bean));
					break;
				case FloatType:
					items.add(addFloatField(param, bean));
					break;
				case IntegerType:
					items.add(addIntField(param, bean));
					break;
				case StringType:
				case OutputFileType:
					items.add(addStringField(param, bean));
					break;
				case InputFileType:
				case SequenceType:
					if (data.required.contains(param.getName()))
						items.addAll(new MyDataItem(param, bean, true).getItems());
					else
						items.addAll(new MyDataItem(param, bean).getItems());
					break;
				case SingleSelectionType:
					items.add(addSelectionField(param, bean));
					break;
				case MultipleSelectionType:
					items.add(addMultiSelectionField(param, bean));
					break;
				case ParagraphType:
					Paragraph paragraph = (Paragraph) param;
					List<FormItem> rets = addParagraphField(paragraph);
					boolean hasVisibleElements = false;

					List<String> ids = new LinkedList<String>();
					for (FormItem item : rets)
					{
						if (!(item instanceof HiddenItem))
						{
							hasVisibleElements = true;
						}
						ids.add(item.getName());
					}

					if (!hasVisibleElements)
					{
						items.addAll(rets);
						break;
					}
					SectionItem si = new SectionItem();
					si.setDefaultValue(paragraph.getPrompt() == null ? paragraph.getName() : paragraph.getPrompt());
					si.setItemIds(ids.toArray(new String[0]));
					addInfoTooltip(si, param);
					si.setWidth(titleWidth + CELL_WIDTH);
					items.add(si);
					items.addAll(rets);
					break;
				}
			}
		}

		SectionItem si = new SectionItem();
		si.setDefaultValue("Extra Parameters");
		List<FormItem> rets = addExtraParameters(bean);
		List<String> ids = new LinkedList<String>();
		for (FormItem item : rets)
		{
			ids.add(item.getName());
		}
		si.setItemIds(ids.toArray(new String[0]));
		si.setWidth(titleWidth + CELL_WIDTH);
		items.add(si);
		items.addAll(rets);

		setFields(items.toArray(new FormItem[0]));
	}

	@Override
	public SelectItem addMultiSelectionField(Parameter param, ProgramValueBean bean)
	{
		SelectItem si = super.addMultiSelectionField(param, bean);
		RestrictedSelection rs = data.map.getRestrictedSelection(param.getName());
		if (rs == null)
			return si;

		String labels[];
		String values[];
		if (param.getVlist() != null)
		{
			labels = param.getVlist().getLabel().toArray(new String[0]);
			values = param.getVlist().getValue().toArray(new String[0]);
		} else
		{
			labels = new String[0];
			values = new String[0];
		}

		LinkedHashMap<String, String> valueMap = new LinkedHashMap<String, String>();
		for (int i = 0; i < labels.length; i++)
		{
			if (rs.getValue().contains(values[i]))
			{
				valueMap.put(values[i], labels[i]);
			}
		}

		si.setValueMap(valueMap);

		String value = bean.getValue(param.getName());
		if (value == null)
			return si;

		String separator = param.getSeparator();
		String[] values1 = value.split(separator);
		List<String> defaultValues = Arrays.asList(values1);
		defaultValues.removeAll(rs.getValue());
		if (defaultValues.isEmpty())
			// wipe default values already set
			si.setDefaultValues(new String[0]);
		else
			si.setDefaultValues(defaultValues.toArray(new String[0]));
		return si;
	}

	@Override
	protected List<FormItem> addParagraphField(Paragraph paragraph)
	{
		List<FormItem> rets = new LinkedList<FormItem>();
		for (Parameter param : paragraph.getParameters())
		{
			if (data.ommitted.contains(param.getName()))
			{
				continue;
			}
			if (data.hidden.contains(param.getName()))
			{
				HiddenItem fi = new HiddenItem(param.getName());
				fi.setValue(data.bean.getValue(param.getName()));
				rets.add(fi);
				continue;
			}
			if (param.isHidden())
			{
				String value = bean.getValue(param.getName());
				HiddenItem hi = new HiddenItem(param.getName());
				hi.setValue(value);
				rets.add(hi);
			} else
			{
				switch (param.getType())
				{
				case BooleanType:
					rets.add(addBooleanField(param, bean));
					break;
				case FloatType:
					rets.add(addFloatField(param, bean));
					break;
				case IntegerType:
					rets.add(addIntField(param, bean));
					break;
				case StringType:
				case OutputFileType:
					rets.add(addStringField(param, bean));
					break;
				case InputFileType:
				case SequenceType:
					if (data.required.contains(param.getName()))
						rets.addAll(new MyDataItem(param, bean, true).getItems());
					else
						rets.addAll(new MyDataItem(param, bean).getItems());
					break;
				case SingleSelectionType:
					rets.add(addSelectionField(param, bean));
					break;
				case MultipleSelectionType:
					rets.add(addMultiSelectionField(param, bean));
					break;
				case ParagraphType:
					rets.addAll(addParagraphField((Paragraph) param));
					break;
				}
			}
		}
		return rets;

	}

	@Override
	public SelectItem addSelectionField(Parameter param, ProgramValueBean bean)
	{
		SelectItem si = super.addMultiSelectionField(param, bean);
		RestrictedSelection rs = data.map.getRestrictedSelection(param.getName());
		if (rs == null)
			return si;
		String value = bean.getValue(param.getName());
		if (value == null)
		{
			value = "";
		}
		String labels[];
		String values[];
		if (param.getVlist() != null)
		{
			labels = param.getVlist().getLabel().toArray(new String[0]);
			values = param.getVlist().getValue().toArray(new String[0]);
		} else
		{
			labels = new String[0];
			values = new String[0];
		}

		boolean hasDefault = false;
		LinkedHashMap<String, String> valueMap = new LinkedHashMap<String, String>();
		for (int i = 0; i < labels.length; i++)
		{
			if (rs.getValue().contains(values[i]))
			{
				valueMap.put(values[i], labels[i]);
				if (values[i].equals(value))
					hasDefault = true;
			}
		}

		si.setValueMap(valueMap);
		if (!hasDefault)
			si.setDefaultValue((String) null);
		return si;
	}

	@Override
	public void preField(FormItem field, Parameter param, ProgramValueBean bean)
	{
		if (data.required.contains(param.getName()))
			field.setRequired(true);
		super.preField(field, param, bean);
		

	}

}
